package com.vf.cloud.pass.mvc.biz.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.vf.cloud.common.datasource.annotation.Tx;
import com.vf.cloud.common.util.DateUtil;
import com.vf.cloud.common.util.R;
import com.vf.cloud.common.util.UuidUtil;
import com.vf.cloud.common.util.WebUtils;
import com.vf.cloud.pass.common.domain.biz.Project;
import com.vf.cloud.pass.common.domain.biz.Scene;
import com.vf.cloud.pass.common.domain.biz.SceneShare;
import com.vf.cloud.pass.common.domain.biz.SceneUserPermission;
import com.vf.cloud.pass.common.domain.sys.Dict;
import com.vf.cloud.pass.common.domain.sys.DictItem;
import com.vf.cloud.pass.common.domain.sys.User;
import com.vf.cloud.pass.common.repository.base.Thumbnail;
import com.vf.cloud.pass.common.util.FileUtil;
import com.vf.cloud.pass.mvc.biz.service.IThumbnail;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("/biz/scene")
public class SceneController {

	@Autowired
	private IThumbnail thumbnailImpl;

	@GetMapping(value = { "/list" }, produces = "application/json; charset=utf-8")
	public R<Page<Scene>> findList(HttpServletRequest request,
			@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "status", required = false, defaultValue = "") String status,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {

		String sqlExceptSelect = " FROM " + Scene.TABLE_NAME + " o  WHERE 1=1 ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' ) ";
		}
		sqlExceptSelect += "  ORDER BY   O.UPDATE_TIME asc ";
		Page<Scene> pages = Scene.dao.paginate(cur, limit, "select * ", sqlExceptSelect);
		return R.ok(pages);
	}

	
	@GetMapping(value = { "/market/list" }, produces = "application/json; charset=utf-8")
	public R<List<Project>> findMarketList(HttpServletRequest request,
			@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "status", required = false, defaultValue = "") String status,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {

		String sqlExceptSelect = " from biz_project a , biz_scene b  WHERE a.type='1' and a.scene_id=b.id ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( b.NAME LIKE '%" + keywords + "%' ) ";
		}
		sqlExceptSelect += "  ORDER BY   b.UPDATE_TIME desc ";
		List<Project> list = Project.dao.find(
				"select a.id , a.scene_id ,b.name ,b.size,b.version ,b.update_time " +
				sqlExceptSelect);
		return R.ok(list);
	}
	
	
	@GetMapping(value = { "/my/list" }, produces = "application/json; charset=utf-8")
	public R<Page<Scene>> findMyList(HttpServletRequest request,
			@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {
		
		String sqlExceptSelect = " FROM " + Scene.TABLE_NAME + " o  WHERE 1=1 ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' ) ";
		}

		sqlExceptSelect += " AND ( o.id in (select scene_id from biz_scene_user_permission where org_id=(select org_id from sys_user where id='"
				+ WebUtils.getCurUserID(request) + "' )  and status='1' ) or o.is_public='1'  ) ";
		sqlExceptSelect += "  ORDER BY   O.UPDATE_TIME asc ";
		
		Page<Scene> pages = Scene.dao.paginate(cur, limit, "select * ", sqlExceptSelect);

		return R.ok(pages);
	}
	
	
	
	

	@Tx
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public R<Scene> save(MultipartFile file, Scene model) {
		try {
			Thumbnail thumbnailEntity = null;
			if (file != null) {
				thumbnailEntity = new Thumbnail();
				thumbnailEntity.setSize(file.getSize());
				thumbnailEntity.setName(model.getName());
				thumbnailEntity.setContentType(file.getContentType());
				thumbnailEntity.setUploadDate(new Date(System.currentTimeMillis()));
				thumbnailEntity.setContent(new Binary(file.getBytes()));
			}

			if (StrKit.isBlank(model.getName())) {
				return R.failed("名称不可以为空！");
			}

			if (StrKit.isBlank(model.getZipFile())) {
				return R.failed("场景包路径无效必填！");
			}

			if (StrKit.isBlank(model.getExeFilePath())) {
				return R.failed("场景可执行文件路径必填！");
			}

			File f = new File(model.getZipFile());
			if (!f.exists()) {
				return R.failed("场景包路径无效！");
			}

			if (StrKit.notBlank(model.getId())) {
				model.setUpdateTime(DateUtil.getLocalDateTime());
				model.setVersion(model.getVersion() + 0.1);
				model.setSize(FileUtil.formatFileSize(f.length()));
				if (model.update()) {
					if (thumbnailEntity != null) {
						try {
							thumbnailEntity.setId(model.getId());
							thumbnailImpl.save(thumbnailEntity);
						} catch (Exception e) {
						}
					}
					return R.ok(model);
				} else {
					return R.failed("更新失败！");
				}
			} else {
				model.setId(UuidUtil.getUUID());
				model.setSize(FileUtil.formatFileSize(f.length()));
				model.setUpdateTime(DateUtil.getLocalDateTime());
				model.setCreateTime(DateUtil.getLocalDateTime());
				if (model.save()) {
					if (thumbnailEntity != null) {
						try {
							thumbnailEntity.setId(model.getId());
							thumbnailImpl.save(thumbnailEntity);
						} catch (Exception e) {
						}
					}
					return R.ok(model);
				} else {
					return R.failed("保存失败！");
				}
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@Tx
	@RequestMapping(value = "/deleteById", method = RequestMethod.GET)
	public R<String> deleteById(@RequestParam(name = "id") String id) throws Exception {
		try {
			Scene role = Scene.dao.findById(id);
			if (role == null)
				return R.failed("数据不存在，刷新后尝试!");
			if (role.delete()) {
				try {
					thumbnailImpl.deleteById(role.getId());
				} catch (Exception e) {
				}
				return R.ok();
			}

			return R.failed("失败！");
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@RequestMapping(value = "/getById", method = RequestMethod.GET)
	public R<Scene> getById(@RequestParam(name = "id") String id) throws Exception {
		try {
			Scene sever = Scene.dao.findById(id);
			if (sever == null)
				return R.failed("数据不存在，刷新后尝试!");
			return R.ok(sever);
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@GetMapping(value = "/thumbnail/{id}", produces = { MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE })
	@ResponseBody
	public byte[] image(@PathVariable String id) {
		byte[] data = null;
		Thumbnail thumbnail = thumbnailImpl.findById(id);
		if (thumbnail != null) {
			data = thumbnail.getContent().getData();
		}
		return data;
	}

	@RequestMapping(value = "/share", method = RequestMethod.GET)
	public R<SceneShare> share(@RequestParam(name = "sceneId") String sceneId) throws Exception {

		try {

			Scene scene = Scene.dao.findById(sceneId);
			if (scene == null) {
				return R.failed();
			}
			SceneShare sceneShare = new SceneShare();
			sceneShare.setId(UuidUtil.getUUID());
			sceneShare.setSceneId(scene.getId());
			sceneShare.setName(scene.getName());
			sceneShare.setCreateTime(DateUtil.getLocalDateTime());
			sceneShare.setLimitedTime(1);
			sceneShare.setResX(scene.getResX());
			sceneShare.setResY(scene.getResY());
			sceneShare.setUrl(String.format("%s", sceneShare.getId()));

			String format = "png";
			Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
			hints.put(EncodeHintType.MARGIN, 1);

			BitMatrix bitMatrix = new MultiFormatWriter().encode(String.format("%s", sceneShare.getId()),
					BarcodeFormat.QR_CODE, 400, 400, hints);
			BufferedImage image = toBufferedImage(bitMatrix);
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			ImageIO.write(image, format, os);

			Thumbnail thumbnailEntity = new Thumbnail();
			thumbnailEntity.setId(sceneShare.getId());
			thumbnailEntity.setSize(1);
			thumbnailEntity.setUploadDate(new Date(System.currentTimeMillis()));
			thumbnailEntity.setContent(new Binary(os.toByteArray()));
			if (sceneShare.save()) {
				thumbnailImpl.save(thumbnailEntity);
				os.close();
				return R.ok(sceneShare);
			} else {
				return R.failed();
			}
		} catch (IOException e) {
			return R.failed(e.getMessage());
		}

	}

	private final int BLACK = 0xFF000000;
	private final int WHITE = 0xFFFFFFFF;

	public BufferedImage toBufferedImage(BitMatrix matrix) {
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
			}
		}
		return image;
	}

	@RequestMapping(value = "/updateShare", method = RequestMethod.POST)
	public R<SceneShare> updateShare(SceneShare model) {
		try {
			SceneShare sceneShare = SceneShare.dao.findById(model.getId());
			if (sceneShare == null) {
				return R.failed();
			}
			if (model.update()) {
				return R.ok(sceneShare);
			} else {
				return R.failed();
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@GetMapping(value = { "/perms" }, produces = "application/json; charset=utf-8")
	public R<Page<User>> perms(@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "sceneId", required = true, defaultValue = "") String sceneId,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {

		String sqlExceptSelect = " from sys_user a LEFT JOIN biz_scene_user_permission b on a.org_id=b.org_id and b.scene_id='"
				+ sceneId + "'  where a.is_sub_account='0' ";

		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( a.NAME LIKE '%" + keywords + "%' ) ";
		}
		sqlExceptSelect += "  ORDER BY   a.UPDATE_TIME desc ";
		Page<User> pages = User.dao.paginate(cur, limit,
				"select a.id,a.name,a.phone,a.org_id,a.org_name, b.`limit` ,b.`status` ", sqlExceptSelect);
		return R.ok(pages);
	}

	@Tx
	@RequestMapping(value = "/savePerms", method = RequestMethod.POST)
	public R<SceneUserPermission> savePerms(HttpServletRequest request, SceneUserPermission model) {
		try {

			SceneUserPermission sceneUserPermission = SceneUserPermission.dao.findByIds(model.getOrgId(),
					model.getSceneId());
			if (sceneUserPermission == null) {
				User user = WebUtils.getCurUser(request);
				if (user != null) {
					model.setCreateBy(user.getId());
				}
				model.setCreateTime(DateUtil.getLocalDateTime());
				if (model.save()) {
					return R.ok("授权成功.",model);
				} else {
					return R.failed("授权失败.");
				}
			} else {
				model.setUpdateTime(DateUtil.getLocalDateTime());
				User user = WebUtils.getCurUser(request);
				if (user != null) {
					model.setUpdateBy(user.getId());
				}
				model.setUpdateTime(DateUtil.getLocalDateTime());
				if (model.update()) {
					return R.ok("授权成功.",model);
				} else {
					return R.failed("授权失败.");
				}
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

	@RequestMapping(value = "/getTypes", method = RequestMethod.GET)
	public R<Dict> getTypes() throws Exception {
		try {

			Dict dict = Dict.dao.findByCode("Industry");
			if (dict != null) {
				List<DictItem> items = DictItem.dao.find(
						"select * from " + DictItem.TABLE_NAME + " where DICT_ID=? order by sort asc ", dict.getId());
				dict.setItems(items);
				return R.ok(dict);
			} else {
				return R.failed();
			}
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}
	
	@Tx
	@RequestMapping(value = "/publish", method = RequestMethod.POST)
	public R<Scene> publish(HttpServletRequest request,@RequestParam(name = "id") String id) {
		try {
			Scene scene=Scene.dao.findById(id);
			if(scene==null) {
				return R.failed("数据不存在，请刷新后尝试.");
			}
			if(StrKit.equals("1", scene.getIsPublic())) {
				return R.failed("场景已发布，无需重复操作.");
			}
			scene.setIsPublic("1");
			if(scene.update()) {
				Project  project=new Project();
				project.setId(UuidUtil.getUUID());
				project.setType("1");
				project.setName(scene.getName());
				project.setSceneId(scene.getId());
				User user = WebUtils.getCurUser(request);
				if (user != null) {
					project.setOrgId(user.getOrgId());
					project.setCreateBy(user.getId());
				}
				project.setCreateTime(DateUtil.getLocalDateTime());
				if (project.save()) {
					return R.ok();
				}
			}
			throw new Exception("发布失败.");
		} catch (Exception e) {
			return R.failed(e.getMessage());
		}
	}

}
